// draw-core.ts
import { Plugin, PluginKey } from "prosemirror-state";

export const drawKey = new PluginKey("draw");

export function createDrawPlugin(options) {
    return new Plugin({
        key: drawKey,
        view(editorView) {
            const draw = new DrawController(editorView, options);
            // draw.init();
            // draw.addHook('render', 'paragraph', (node, dom) => {
            //     dom.classList.add('my-paragraph');
            //     return dom;
            // });
            return {
                update(view, prevState) {
                    draw.update(view, prevState);
                },
                destroy() {
                    draw.destroy();
                },
            };
        },
    });
}

export class DrawController {
    constructor(view, options = {}) {
        this.view = view;
        this.options = options;
        this.hooks = this.createHooks(view.state.schema);
        console.log("createDrawPlugin", this.hooks);
    }

    createHooks(schema) {
        const hooks = { render: {}, afterRender: {}, childContainer: {}, afterChildRender: {} };
        const keys = Object.keys(schema.nodes);
        keys.forEach((name) => {
            hooks.render[name] = [];
            hooks.afterRender[name] = [];
            hooks.childContainer[name] = [];
            hooks.afterChildRender[name] = [];
        })
        // schema.nodes.forEach((_type, name) => {
        //   hooks.render[name] = [];
        //   hooks.afterRender[name] = [];
        //   hooks.childContainer[name] = [];
        //   hooks.afterChildRender[name] = [];
        // });
        // schema.marks.forEach((_type, name) => {
        //   hooks.render[name] = hooks.render[name] || [];
        // });
        return hooks;
    }

    addHook(type, nodeName, handler) {
        console.log('addHook', type, nodeName, handler);
        this.hooks[type][nodeName]?.push(handler);
    }

    runHook(type, node, ...args) {
        console.log('runHook', type, node.type.name, ...args);
        let result = args[0];
        for (const fn of this.hooks[type][node.type.name] || []) {
            result = fn(node, result, ...args.slice(1)) ?? result;
        }
        return result;
    }
    update(view, prevState) {
        // this.view = view;
        console.log("update", view, prevState);
    }
}

export function createDrawAwareNodeViews(draw, schema, original = {}) {
    const wrapped = {};
    schema.nodes.forEach((_type, name) => {
        const factory = original[name] || defaultNodeView;
        wrapped[name] = createNodeViewProxy(draw, factory);
    });
    return wrapped;
}

function defaultNodeView(node) {
    const dom = document.createElement(node.isTextblock ? "div" : "span");
    dom.className = `node-${node.type.name}`;
    const contentDOM = node.isTextblock ? document.createElement("div") : null;
    if (contentDOM) dom.appendChild(contentDOM);
    return { dom, contentDOM };
}
